package com.caseprocessing.service;

import com.caseprocessing.model.*;
import java.util.*;

/**
 * 文书类型分类器
 * 负责识别文档片段的具体文书类型
 */
public class DocumentClassifier {
    
    private Map<DocumentType, DocumentTemplate> templates;
    private KeywordClassifier keywordClassifier;
    private LayoutClassifier layoutClassifier;
    
    public DocumentClassifier() {
        this.templates = loadDocumentTemplates();
        this.keywordClassifier = new KeywordClassifier();
        this.layoutClassifier = new LayoutClassifier();
    }
    
    /**
     * 对文档片段进行分类
     */
    public DocumentType classify(DocumentSegment segment) {
        if (segment == null || segment.getPages() == null || segment.getPages().isEmpty()) {
            return DocumentType.OTHER;
        }
        
        // 1. 关键词匹配评分
        Map<DocumentType, Double> keywordScores = keywordClassifier.calculateKeywordScores(segment);
        
        // 2. 布局特征匹配评分
        Map<DocumentType, Double> layoutScores = layoutClassifier.calculateLayoutScores(segment);
        
        // 3. 综合评分计算
        DocumentType bestMatch = calculateWeightedScore(keywordScores, layoutScores);
        
        // 4. 设置分类置信度
        double confidence = calculateClassificationConfidence(bestMatch, keywordScores, layoutScores);
        segment.setDocumentType(bestMatch);
        segment.setConfidence(Math.min(segment.getConfidence(), confidence));
        
        return bestMatch;
    }
    
    /**
     * 计算综合评分
     */
    private DocumentType calculateWeightedScore(Map<DocumentType, Double> keywordScores, 
                                              Map<DocumentType, Double> layoutScores) {
        Map<DocumentType, Double> combinedScores = new HashMap<>();
        
        // 获取所有可能的文书类型
        Set<DocumentType> allTypes = new HashSet<>();
        allTypes.addAll(keywordScores.keySet());
        allTypes.addAll(layoutScores.keySet());
        
        // 计算加权综合得分
        for (DocumentType type : allTypes) {
            double keywordScore = keywordScores.getOrDefault(type, 0.0);
            double layoutScore = layoutScores.getOrDefault(type, 0.0);
            
            // 关键词权重0.7，布局权重0.3
            double combinedScore = keywordScore * 0.7 + layoutScore * 0.3;
            combinedScores.put(type, combinedScore);
        }
        
        // 找到得分最高的类型
        return combinedScores.entrySet().stream()
                .max(Map.Entry.comparingByValue())
                .map(Map.Entry::getKey)
                .orElse(DocumentType.OTHER);
    }
    
    /**
     * 计算分类置信度
     */
    private double calculateClassificationConfidence(DocumentType bestMatch,
                                                   Map<DocumentType, Double> keywordScores,
                                                   Map<DocumentType, Double> layoutScores) {
        double keywordScore = keywordScores.getOrDefault(bestMatch, 0.0);
        double layoutScore = layoutScores.getOrDefault(bestMatch, 0.0);
        
        // 如果两种方法都有较高置信度，则总置信度高
        if (keywordScore > 0.8 && layoutScore > 0.6) {
            return 0.9;
        } else if (keywordScore > 0.6 || layoutScore > 0.6) {
            return 0.7;
        } else {
            return 0.5;
        }
    }
    
    /**
     * 加载文书模板配置
     */
    private Map<DocumentType, DocumentTemplate> loadDocumentTemplates() {
        Map<DocumentType, DocumentTemplate> templates = new HashMap<>();
        
        // 处罚决定书模板
        DocumentTemplate decisionTemplate = new DocumentTemplate();
        decisionTemplate.setRequiredElements(Arrays.asList("标题", "文号", "当事人", "处罚内容", "签名", "印章"));
        decisionTemplate.setKeywords(Arrays.asList("处罚决定书", "行政处罚", "决定", "违法行为"));
        templates.put(DocumentType.CASE_DECISION, decisionTemplate);
        
        // 证据清单模板
        DocumentTemplate evidenceTemplate = new DocumentTemplate();
        evidenceTemplate.setRequiredElements(Arrays.asList("标题", "序号", "证据名称", "页数"));
        evidenceTemplate.setKeywords(Arrays.asList("证据清单", "证据目录", "证据材料"));
        templates.put(DocumentType.EVIDENCE_LIST, evidenceTemplate);
        
        // 调查笔录模板
        DocumentTemplate recordTemplate = new DocumentTemplate();
        recordTemplate.setRequiredElements(Arrays.asList("标题", "时间", "地点", "被调查人", "调查人", "记录人"));
        recordTemplate.setKeywords(Arrays.asList("调查笔录", "询问笔录", "调查记录"));
        templates.put(DocumentType.INVESTIGATION_RECORD, recordTemplate);
        
        return templates;
    }
    
    /**
     * 关键词分类器
     */
    static class KeywordClassifier {
        
        public Map<DocumentType, Double> calculateKeywordScores(DocumentSegment segment) {
            Map<DocumentType, Double> scores = new HashMap<>();
            String content = segment.getFullText().toLowerCase();
            
            // 为每种文书类型计算关键词匹配得分
            for (DocumentType type : DocumentType.values()) {
                double score = calculateTypeKeywordScore(content, type);
                if (score > 0) {
                    scores.put(type, score);
                }
            }
            
            return scores;
        }
        
        /**
         * 计算特定文书类型的关键词得分
         */
        private double calculateTypeKeywordScore(String content, DocumentType type) {
            String[] keywords = type.getKeywords();
            if (keywords.length == 0) {
                return 0.0;
            }
            
            int matchCount = 0;
            double totalWeight = 0.0;
            
            for (String keyword : keywords) {
                if (content.contains(keyword.toLowerCase())) {
                    matchCount++;
                    // 不同关键词有不同权重
                    totalWeight += getKeywordWeight(keyword, type);
                }
            }
            
            // 计算匹配率和权重得分
            double matchRate = (double) matchCount / keywords.length;
            return Math.min(1.0, matchRate + totalWeight / keywords.length);
        }
        
        /**
         * 获取关键词权重
         */
        private double getKeywordWeight(String keyword, DocumentType type) {
            // 核心关键词权重更高
            if (type == DocumentType.CASE_DECISION && keyword.equals("处罚决定书")) {
                return 0.8;
            } else if (type == DocumentType.EVIDENCE_LIST && keyword.equals("证据清单")) {
                return 0.8;
            } else if (type == DocumentType.INVESTIGATION_RECORD && keyword.equals("调查笔录")) {
                return 0.8;
            }
            
            return 0.3; // 默认权重
        }
    }
    
    /**
     * 布局特征分类器
     */
    static class LayoutClassifier {
        
        public Map<DocumentType, Double> calculateLayoutScores(DocumentSegment segment) {
            Map<DocumentType, Double> scores = new HashMap<>();
            
            for (Page page : segment.getPages()) {
                if (page.getLayoutElements() != null) {
                    for (LayoutElement element : page.getLayoutElements()) {
                        updateScoresFromLayoutElement(scores, element);
                    }
                }
            }
            
            return scores;
        }
        
        /**
         * 根据布局元素更新得分
         */
        private void updateScoresFromLayoutElement(Map<DocumentType, Double> scores, LayoutElement element) {
            switch (element.getType()) {
                case "signature_area":
                    if (element.hasSignature()) {
                        // 有签名的文档更可能是决定书类
                        incrementScore(scores, DocumentType.CASE_DECISION, 0.3);
                        incrementScore(scores, DocumentType.NOTIFICATION, 0.2);
                    }
                    break;
                    
                case "seal_area":
                    if (element.hasSeal()) {
                        // 有印章的文档更可能是正式决定书
                        incrementScore(scores, DocumentType.CASE_DECISION, 0.4);
                    }
                    break;
                    
                case "table":
                    // 表格结构更可能出现在证据清单或目录中
                    incrementScore(scores, DocumentType.EVIDENCE_LIST, 0.3);
                    incrementScore(scores, DocumentType.DIRECTORY, 0.2);
                    break;
                    
                case "header":
                    // 标准页眉格式
                    String headerContent = element.getContentText().toLowerCase();
                    if (headerContent.contains("笔录")) {
                        incrementScore(scores, DocumentType.INVESTIGATION_RECORD, 0.3);
                        incrementScore(scores, DocumentType.HEARING_RECORD, 0.3);
                    }
                    break;
            }
        }
        
        /**
         * 增加指定类型的得分
         */
        private void incrementScore(Map<DocumentType, Double> scores, DocumentType type, double increment) {
            scores.put(type, scores.getOrDefault(type, 0.0) + increment);
        }
    }
    
    /**
     * 批量分类文档片段
     */
    public List<DocumentSegment> classifyAll(List<DocumentSegment> segments) {
        for (DocumentSegment segment : segments) {
            classify(segment);
        }
        return segments;
    }
    
    /**
     * 获取分类统计信息
     */
    public Map<DocumentType, Integer> getClassificationStatistics(List<DocumentSegment> segments) {
        Map<DocumentType, Integer> statistics = new HashMap<>();
        
        for (DocumentSegment segment : segments) {
            DocumentType type = segment.getDocumentType();
            if (type != null) {
                statistics.put(type, statistics.getOrDefault(type, 0) + 1);
            }
        }
        
        return statistics;
    }
    
    /**
     * 验证分类结果的合理性
     */
    public boolean validateClassificationResults(List<DocumentSegment> segments) {
        Map<DocumentType, Integer> statistics = getClassificationStatistics(segments);
        
        // 检查是否有基本的必要文书
        boolean hasDecision = statistics.getOrDefault(DocumentType.CASE_DECISION, 0) > 0;
        boolean hasEvidence = statistics.getOrDefault(DocumentType.EVIDENCE_LIST, 0) > 0;
        
        // 一个完整的案卷通常应该包含处罚决定书
        if (!hasDecision && segments.size() > 3) {
            System.out.println("警告：未识别到处罚决定书，可能存在分类错误");
            return false;
        }
        
        return true;
    }
}